﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExamAnalysis.Model;
using MathNet.Numerics;

namespace ExamAnalysis.Core.Statistics
{
    public static class Report
    {
        const int EXCELLENT_SCORE = 80;
        const int PASS_SCORE = 60;
        const int FULL_SCORE = 100;

        public static List<int> GetStudentIDs(int classid, string stuCondition)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                List<int> studentIDs = new List<int>();
                if (stuCondition.Length > 0)
                {
                    studentIDs.AddRange(
                        db.StudentInfo
                            .Where(p =>
                                p.StudentType == stuCondition
                                && p.ClassID == classid)
                            .Select(p => p.StudentID)
                            .ToList()
                    );
                }
                else
                {
                    studentIDs.AddRange(
                        db.StudentInfo
                            .Where(p => p.ClassID == classid)
                            .Select(p => p.StudentID)
                            .ToList()
                    );
                }
                return studentIDs;
            }
        }

        public static List<double> BuildScoreList(List<int> studentIDs, List<int> itemIDs)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                List<double> scores = new List<double>();
                foreach (int studentID in studentIDs)
                {
                    double total = 0;
                    bool missingFlag = false;
                    foreach (int a in itemIDs)
                    {
                        var b = db.StudentInExamItem
                            .Where(p => p.StudentID == studentID
                                && p.ExamItemID == a)
                            .SingleOrDefault();
                        if (b != null)
                        {
                            total += Convert.ToDouble(b.Score);
                        }
                        else
                        {
                            missingFlag = true;
                        }
                    }
                    if (!missingFlag) scores.Add(total);
                }
                return scores;
            }
        }

        public static List<double> BuildTotalScoreList(List<int> studentIDs, List<int> itemIDs)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                List<double> scores = new List<double>();
                foreach (int studentID in studentIDs)
                {
                    double total = 0;
                    bool missingFlag = false;
                    foreach (int a in itemIDs)
                    {
                        var b = db.StudentInExamItem
                            .Where(p => p.StudentID == studentID
                                && p.ExamItemID == a)
                            .SingleOrDefault();
                        if (b != null)
                        {
                            total += Convert.ToDouble(b.ExamItems.ItemScore);
                        }
                        else
                        {
                            missingFlag = true;
                        }
                    }
                    if (!missingFlag) scores.Add(total);
                }
                return scores;
            }
        }

        public static List<int> GetStudentIDs(int classid)
        {
            return GetStudentIDs(classid, "");
        }
        /// <summary>
        /// 总分整体
        /// </summary>
        /// <param name="classes"></param>
        /// <param name="itemgroups"></param>
        /// <returns></returns>
        public static List<MacroReportEntity> ProcessMacroReport(string itemType, int itemID, List<int> stuClass, string stuCondition)
        {
            //personType:class
            //itemType:item/itemgroup
            List<int> studentIDs = new List<int>();
            List<int> itemIDs = new List<int>();
            List<MacroReportEntity> results = new List<MacroReportEntity>();
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                //提取基本数据itemIDs
                itemIDs = GetExamItemList(itemType, itemID);

                 //提取班级
                foreach (int classid in stuClass)
                {
                    //读取学生
                    studentIDs = GetStudentIDs(classid, stuCondition);
                    
                    //合计分数
                    List<double> scores = BuildScoreList(studentIDs, itemIDs);
                    List<double> totalscores = BuildTotalScoreList(studentIDs, itemIDs);
                    //班级统计
                    //MathNet.Numerics.Statistics.Statistics.

                    MacroReportEntity result = new MacroReportEntity();
                        result.ClassID = classid;
                        result.ClassName = db.ClassInfo.Where(p => p.ClassID == classid).Single().ClassAliasName;
                        //result.AvgScore = Convert.ToDecimal(scores.Average());

                        result.AvgScore = Convert.ToDecimal(scores.Average());
                        result.ScoreRate = Convert.ToDecimal(scores.Sum() * 100 /totalscores.Sum());
                        result.ActualStudentsCount = scores.Count();
                        result.TheoryStudentCount = db.StudentInfo.Where(p => p.ClassID == classid).Count();
                        result.MaxScore = Convert.ToDecimal(scores.Max());
                        result.MinScore = Convert.ToDecimal(scores.Min());
                        result.StdScore = Convert.ToDecimal(MathNet.Numerics.Statistics.Statistics.PopulationStandardDeviation(scores));
                        result.MADScore = Convert.ToDecimal(Method.CalculateMAD(scores));
                        result.MedianScore = Convert.ToDecimal(MathNet.Numerics.Statistics.Statistics.Median(scores));
                        var percentile = new MathNet.Numerics.Statistics.Percentile(scores);
                        result.QuartileScore1 = Convert.ToDecimal(percentile.Compute(0.25));
                        result.QuartileScore3 = Convert.ToDecimal(percentile.Compute(0.75));
                        result.ExcellentRatio = Method.CalculatePeriodCount(EXCELLENT_SCORE, FULL_SCORE, scores) * 100 / scores.Count();
                        result.PassRatio = Method.CalculatePeriodCount(PASS_SCORE, FULL_SCORE, scores) * 100 / scores.Count();
                        result.LowRatio = Method.CalculatePeriodCount(0, PASS_SCORE - 0.01, scores) * 100 / scores.Count();
                        result.Count1 = Method.CalculatePeriodCount(0, 60 - 0.01, scores);
                        result.Count2 = Method.CalculatePeriodCount(60, 70 - 0.01, scores);
                        result.Count3 = Method.CalculatePeriodCount(70, 80 - 0.01, scores);
                        result.Count4 = Method.CalculatePeriodCount(80, 90 - 0.01, scores);
                        result.Count5 = Method.CalculatePeriodCount(90, 100, scores);
                        if (result.ActualStudentsCount > 0)
                        {
                            results.Add(result);
                        }
                }
                //整体分析
                foreach (MacroReportEntity item in results)
                {
                    item.AvgScoreRank = Method.CalculateRankCount(
                        item.AvgScore, results.Select(p => p.AvgScore).ToList());
                    item.ExcellentRatioRank = Method.CalculateRankCount(
                        item.ExcellentRatio, results.Select(p => p.ExcellentRatio).ToList());
                    item.PassRatioRank = Method.CalculateRankCount(
                        item.PassRatio, results.Select(p => p.PassRatio).ToList());
                    item.LowRatioRank = Method.CalculateRankCount(
                        item.LowRatio, results.Select(p => p.LowRatio).ToList());
                }
            }
            return results;
        }

        public static List<int> GetExamItemList(string itemType, int itemID)
        {
            List<int> itemIDs = new List<int>();
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                switch (itemType)
                {
                    case "ExamGroup":
                        var exams = db.ExamInGroup
                            .Where(p => p.ExamGroupID == itemID)
                            .Select(p => p.ExamInfo.ExamID)
                            .ToList();
                        foreach (var exam in exams)
                        {
                            var newitems = db.ExamItems
                            .Where(p => p.ExamItemsGroup.ExamInfo.ExamID == exam)
                            .Select(p => p.ExamItemID)
                            .ToList();
                            itemIDs.AddRange(newitems);
                        }
                        break;
                    case "ExamInfo":
                        itemIDs = db.ExamItems
                            .Where(p => p.ExamItemsGroup.ExamInfo.ExamID == itemID)
                            .Select(p => p.ExamItemID)
                            .ToList();
                        break;
                    case "ExamItemsGroup":
                        itemIDs = db.ExamItems
                            .Where(p => p.ExamItemGroupID == itemID)
                            .Select(p => p.ExamItemID)
                            .ToList();
                        break;
                };
            }
            return itemIDs;
        }

        /// <summary>
        /// 总分学生
        /// </summary>
        /// <param name="itemType"></param>
        /// <param name="itemID"></param>
        /// <param name="classID"></param>
        /// <returns></returns>
        public static List<MacroStudentReportEntity> ProcessMacroStudentReport(string itemType, int itemID, List<int> stuClass)
        {
            List<int> studentIDs = new List<int>();
            List<int> itemIDs = new List<int>();
            List<MacroStudentReportEntity> results = new List<MacroStudentReportEntity>();
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                //提取基本数据itemIDs
                itemIDs = GetExamItemList(itemType, itemID);
                
                //提取班级
                foreach (int classid in stuClass)
                {
                    //读取学生
                    studentIDs = GetStudentIDs(classid);

                    //合计分数
                    foreach (int studentID in studentIDs)
                    {
                        //分数合并
                        double total = 0;
                        bool missingFlag = false;
                        
                        if (itemType == "ExamInfo")
                        {
                            //对单科优化缓存
                            var exam = db.StudentInExam.Where(p => p.StudentID == studentID && p.ExamID == itemID).SingleOrDefault();
                            if (exam != null)
                            {
                                total = Convert.ToDouble(exam.Score);
                            }
                            else
                            {
                                missingFlag = true;
                            }
                        }
                        else
                        {
                            //小分统计
                            foreach (int a in itemIDs)
                            {
                                var b = db.StudentInExamItem
                                    .Where(p => p.StudentID == studentID
                                        && p.ExamItemID == a)
                                    .SingleOrDefault();
                                if (b != null)
                                {
                                    total += Convert.ToDouble(b.Score);
                                }
                                else
                                {
                                    missingFlag = true;
                                }
                            }
                        }
                        if (!missingFlag)
                        {
                            //加入报告
                            MacroStudentReportEntity result = new MacroStudentReportEntity();
                                result.StudentID = studentID;
                                result.ClassName = db.ClassInfo.Where(p => p.ClassID == classid).Single().ClassAliasName;
                                result.ClassType = db.ClassInfo.Where(p => p.ClassID == classid).Single().ClassType;
                                result.ClassID = classid;
                                var student = db.StudentInfo.Where(p => p.StudentID == studentID).Single();
                                result.StuCode = student.StudentCode;
                                result.StuName = student.StudentName;
                                result.StuType = student.StudentType;
                                result.Score = Convert.ToDecimal(total);
                            results.Add(result);
                        }
                    }
                }
                
                //整体分析
                decimal avg = results.Select(p => p.Score).Average();
                decimal std = Convert.ToDecimal(MathNet.Numerics.Statistics.Statistics.PopulationStandardDeviation(results.Select(p => Convert.ToDouble(p.Score)).ToList()));
                foreach (MacroStudentReportEntity item in results)
                {
                    //-->对单科加入缓存（注意，排名算法有问题，在这里做改正）<--
                    if (itemType == "ExamInfo")
                    {
                        //RankOfClass
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_RankOfClass,
                            "StudentID",item.StudentID,"ExamID",itemID))
                        {
                            item.RankOfClass = Convert.ToInt32(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_RankOfClass,
                                "StudentID",item.StudentID,"ExamID",itemID));
                        }
                        else
                        {
                            item.RankOfClass = Method.CalculateRankCount(item.Score,
                                db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassID == item.ClassID && p.ExamID == itemID)
                                    .Select(p => p.Score).ToList());
                            Cache.WriteCache(
                                item.RankOfClass.ToString(),
                                Cache.CacheType.MacroStudentReport_RankOfClass,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //PercentOfClass
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_PercentOfClass,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.PercentOfClass = Convert.ToDecimal(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_PercentOfClass,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            item.PercentOfClass = Method.CalculatePeriodCount(
                                0, Convert.ToDouble(item.Score) - 0.01,
                                db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassID == item.ClassID && p.ExamID == itemID)
                                    .Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassID == item.ClassID && p.ExamID == itemID).Count();
                            Cache.WriteCache(
                                item.PercentOfClass.ToString(),
                                Cache.CacheType.MacroStudentReport_PercentOfClass,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //RankOfGrade
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_RankOfGrade,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.RankOfGrade = Convert.ToInt32(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_RankOfGrade,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            item.RankOfGrade = Method.CalculateRankCount(item.Score,
                                db.StudentInExam
                                    .Where(p => p.ExamID == itemID)
                                    .Select(p => p.Score).ToList());
                            Cache.WriteCache(
                                item.RankOfGrade.ToString(),
                                Cache.CacheType.MacroStudentReport_RankOfGrade,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //PercentOfGrade
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_PercentOfGrade,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.PercentOfGrade = Convert.ToDecimal(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_PercentOfGrade,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            item.PercentOfGrade = Method.CalculatePeriodCount(
                                0, Convert.ToDouble(item.Score) - 0.01,
                                db.StudentInExam
                                    .Where(p => p.ExamID == itemID)
                                    .Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / db.StudentInExam
                                    .Where(p => p.ExamID == itemID).Count();
                            Cache.WriteCache(
                                item.PercentOfGrade.ToString(),
                                Cache.CacheType.MacroStudentReport_PercentOfGrade,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //RankOfClassType
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_RankOfClassType,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.RankOfClassType = Convert.ToInt32(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_RankOfClassType,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            item.RankOfClassType = Method.CalculateRankCount(item.Score,
                                db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassInfo.ClassType == item.ClassType && p.ExamID == itemID)
                                    .Select(p => p.Score).ToList());
                            Cache.WriteCache(
                                item.RankOfClassType.ToString(),
                                Cache.CacheType.MacroStudentReport_RankOfClassType,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //PercentOfClassType
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_PercentOfClassType,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.PercentOfClassType = Convert.ToDecimal(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_PercentOfClassType,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            item.PercentOfClassType = Method.CalculatePeriodCount(
                                0, Convert.ToDouble(item.Score) - 0.01,
                                db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassInfo.ClassType == item.ClassType && p.ExamID == itemID)
                                    .Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / db.StudentInExam
                                    .Where(p => p.StudentInfo.ClassInfo.ClassType == item.ClassType && p.ExamID == itemID).Count();
                            Cache.WriteCache(
                                item.PercentOfClassType.ToString(),
                                Cache.CacheType.MacroStudentReport_PercentOfClassType,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                        //StandardizedScore
                        if (Cache.HasCache(Cache.CacheType.MacroStudentReport_StandardizedScore,
                            "StudentID", item.StudentID, "ExamID", itemID))
                        {
                            item.StandardizedScore = Convert.ToDecimal(
                                Cache.ReadCache(Cache.CacheType.MacroStudentReport_StandardizedScore,
                                "StudentID", item.StudentID, "ExamID", itemID));
                        }
                        else
                        {
                            if (std != 0) item.StandardizedScore = (item.Score - avg) / std;
                            Cache.WriteCache(
                                item.StandardizedScore.ToString(),
                                Cache.CacheType.MacroStudentReport_StandardizedScore,
                                "StudentID", item.StudentID, "ExamID", itemID);
                        }
                    }
                    else
                    {
                        //-->以下保留原样<--
                        //成绩百分位：不高于该考生总成绩的考生人数占全体考生的百分比
                        item.RankOfClass = Method.CalculateRankCount(
                            item.Score, results.Where(p => p.ClassID == item.ClassID).Select(p => p.Score).ToList());
                        item.PercentOfClass = Method.CalculatePeriodCount(
                            0, Convert.ToDouble(item.Score) - 0.01,
                            results
                                .Where(p => p.ClassID == item.ClassID)
                                .Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / results
                                .Where(p => p.ClassID == item.ClassID).Count();
                        item.RankOfGrade = Method.CalculateRankCount(
                            item.Score, results.Select(p => p.Score).ToList());
                        item.PercentOfGrade = Method.CalculatePeriodCount(
                            0, Convert.ToDouble(item.Score) - 0.01,
                            results.Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / results.Count();
                        item.RankOfClassType = Method.CalculateRankCount(
                            item.Score,
                            results
                                .Where(p => db.ClassInfo.Where(q => q.ClassID == p.ClassID).Single().ClassType == db.ClassInfo.Where(r => r.ClassID == item.ClassID).Single().ClassType)
                                .Select(p => p.Score).ToList());
                        item.PercentOfClassType = Method.CalculatePeriodCount(
                            0, Convert.ToDouble(item.Score) - 0.01,
                            results
                            .Where(p => db.ClassInfo.Where(q => q.ClassID == p.ClassID).Single().ClassType == db.ClassInfo.Where(r => r.ClassID == item.ClassID).Single().ClassType)
                            .Select(p => Convert.ToDouble(p.Score)).ToList()) * 100 / results
                            .Where(p => db.ClassInfo.Where(q => q.ClassID == p.ClassID).Single().ClassType == db.ClassInfo.Where(r => r.ClassID == item.ClassID).Single().ClassType).Count();

                        if (std != 0) item.StandardizedScore = (item.Score - avg) / std;
                    }
                }
            }
            //整体分析
            return results;
        }

        /// <summary>
        /// 小分整体
        /// </summary>
        /// <param name="classes"></param>
        /// <param name="itemgroups"></param>
        /// <returns></returns>
        public static List<MicroReportEntity> ProcessMicroReport(int examID)
        {
            List<MicroReportEntity> results = new List<MicroReportEntity>();
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                var items = db.ExamItems.Where(p => p.ExamItemsGroup.ExamID == examID);
                foreach (var item in items)
                {
                    MicroReportEntity result = new MicroReportEntity();
                    result.ExamItemID = item.ExamItemID;
                    result.ItemName = item.ItemName;
                    result.DifficultyLevel = item.DifficultyLevel;
                    result.ItemScore = item.ItemScore;
                    result.KnowledgePointID = item.KnowledgePointID;
                    result.KnowledgePointName = item.KnowledgePointInfo.KnowledgePointName;
                    result.AnswerCount = item.StudentInExamItem.Count();
                    result.CorrectCount = Convert.ToInt32(Math.Round(item.StudentInExamItem.Select(p => p.Score).Sum() / item.ItemScore));
                    result.WrongCount = result.AnswerCount - result.CorrectCount;
                    result.ScoreRate = result.CorrectCount * 100 / item.StudentInExamItem.Count();
                    result.KnowledgePointScoreRate = db.StudentInExamItem
                        .Where(p => p.ExamItems.KnowledgePointID == item.KnowledgePointID)
                        .Select(p => p.Score).Sum() * 100 / db.StudentInExamItem
                        .Where(p => p.ExamItems.KnowledgePointID == item.KnowledgePointID)
                        .Select(p => p.ExamItems.ItemScore).Sum();
                    result.DiffenceDegree = Method.CalCulateDifferenceDegree(0.25M, item.ItemScore, item.StudentInExamItem.Select(p => p.Score).ToList());
                    
                    //偷懒生成法
                    result.Reason1 = 0;
                    result.Reason2 = 0;
                    result.Reason3 = 0;
                    result.Reason4 = 0;
                    result.ReasonPercent1 = 0;
                    result.ReasonPercent2 = 0;
                    result.ReasonPercent3 = 0;
                    result.ReasonPercent4 = 0;
                    var reasons = db.ReasonInfo
                        .Where(p => p.SubjectID == item.ExamItemsGroup.ExamInfo.ExamInCourse.First().CourseInfo.SubjectID)
                        .OrderBy(p => p.ReasonID)
                        .Take(4)
                        .ToArray();
                    int reasonCount = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID && p.ExamItemID==item.ExamItemID)
                            .Count();
                    if (reasons.Count() >= 1)
                    {
                        result.Reason1 = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.ReasonID == reasons[0].ReasonID)
                            .Count();
                        result.ReasonPercent1 = result.Reason1 * 100 / reasonCount;
                    }
                    if (reasons.Count() >= 2)
                    {
                        result.Reason2 = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.ReasonID == reasons[1].ReasonID)
                            .Count();
                        result.ReasonPercent2 = result.Reason2 * 100 / reasonCount;
                    }
                    if (reasons.Count() >= 3)
                    {
                        result.Reason3 = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.ReasonID == reasons[2].ReasonID)
                            .Count();
                        result.ReasonPercent3 = result.Reason3 * 100 / reasonCount;
                    }
                    if (reasons.Count() >= 4)
                    {
                        result.Reason4 = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.ReasonID == reasons[3].ReasonID)
                            .Count();
                        result.ReasonPercent4 = result.Reason4 * 100 / reasonCount;
                    }
                    //选项汇总
                    int ChooseCount = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID && p.ExamItemID == item.ExamItemID)
                            .Count();

                    result.ChooseA = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID 
                                && p.ExamItemID == item.ExamItemID
                                && p.Answer=="A")
                            .Count();
                    result.ChooseB = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.Answer == "B")
                            .Count();
                    result.ChooseC = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.Answer == "C")
                            .Count();
                    result.ChooseD = db.StudentInExamItem
                            .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID
                                && p.ExamItemID == item.ExamItemID
                                && p.Answer == "D")
                            .Count();
                    result.ChoosePercentA = result.ChooseA * 100 / ChooseCount; ;
                    result.ChoosePercentB = result.ChooseB * 100 / ChooseCount; ;
                    result.ChoosePercentC = result.ChooseC * 100 / ChooseCount; ;
                    result.ChoosePercentD = result.ChooseD * 100 / ChooseCount; ;
                    
                    results.Add(result);
                }
            }
            return results;
        }

        public static List<MicroStudentReportEntity> ProcessMicroStudentReport(int examID, int studentID)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext()){
                List<MicroStudentReportEntity> results = new List<MicroStudentReportEntity>();
                var items = db.StudentInExamItem
                    .Where(p => p.ExamItems.ExamItemsGroup.ExamID == examID 
                        && p.StudentID == studentID)
                    .ToList();
                foreach (var item in items)
                {
                    MicroStudentReportEntity result = new MicroStudentReportEntity();
                    result.ItemID = item.ExamItemID;
                    result.ItemName = item.ExamItems.ItemName;
                    result.ItemScore = item.ExamItems.ItemScore;
                    result.Score = item.Score;
                    result.ReasonID = item.ReasonID ?? 0;
                    result.ReasonName = item.ReasonInfo.ReasonName;
                    result.Difficulty = item.ExamItems.DifficultyLevel;
                    result.KnowledgeID = item.ExamItems.KnowledgePointID;
                    result.KnowledgeName = item.ExamItems.KnowledgePointInfo.KnowledgePointName;
                    result.KnowledgeScoreRate =
                        items.Where(p => p.ExamItems.KnowledgePointID == result.KnowledgeID).Select(p => p.Score).Sum() * 100 /
                        items.Where(p => p.ExamItems.KnowledgePointID == result.KnowledgeID).Select(p => p.ExamItems.ItemScore).Sum();
                    results.Add(result);
                }
            return results;
            }
        }

        public static List<CompareReportEntity> ProcessCompareReport(int classID, List<int> examIDs)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                List<CompareReportEntity> results = new List<CompareReportEntity>();
                foreach (int examID in examIDs)
                {
                    CompareReportEntity result = new CompareReportEntity();
                    result.ClassID=classID;
                    result.ClassName = db.ClassInfo.Where(p => p.ClassID == classID).Single().ClassAliasName;
                    result.ExamID = examID;
                    result.ExamName = db.ExamInfo.Where(p => p.ExamID == examID).Single().ExamName;
                    result.Score=db.StudentInExam.Where(p => p.StudentInfo.ClassID == classID && p.ExamID == examID).Select(p=>p.Score).Average();
                    result.CalendarID = db.ExamInfo.Where(p => p.ExamID == examID).Single().CalendarID;
                    result.CalendarName = db.ExamInfo.Where(p => p.ExamID == examID).Single().SchoolCalender.DisplayName;
                    
                    var classes=db.StudentInExam
                        .Where(p => p.ExamID == examID)
                        .Select(p=>p.StudentInfo.ClassID)
                        .Distinct().ToList();
                    List<decimal> scores = new List<decimal>();
                    foreach(int oneclass in classes)
                    {
                        scores.Add(db.StudentInExam.Where(p => p.StudentInfo.ClassID == oneclass && p.ExamID == examID).Select(p=>p.Score).Average());
                    }
                    result.Rank = Method.CalculateRankCount(result.Score, scores);
                    results.Add(result);
                }
                return results;
            }
        }

        public static List<CompareStudentReportEntity> ProcessCompareStudentReport(int stuID, List<int> examIDs)
        {
            using (ExamAnalysisDataContext db = new ExamAnalysisDataContext())
            {
                List<CompareStudentReportEntity> results = new List<CompareStudentReportEntity>();
        
        //decimal Score { get; set; }
        //int Rank { get; set; }
                foreach (int examID in examIDs)
                {
                    CompareStudentReportEntity result = new CompareStudentReportEntity();
                    result.StudentID = stuID;
                    var student=db.StudentInfo.Where(p => p.StudentID == stuID).Single();
                    result.StudentCode = student.StudentCode;
                    result.StudentName = student.StudentName;
                    result.ClassID = student.ClassID;
                    result.ClassName = student.ClassInfo.ClassAliasName;
                    result.ExamID = examID;
                    result.ExamName = db.ExamInfo.Where(p => p.ExamID == examID).Single().ExamName;
                    result.Score = db.StudentInExam.Where(p => p.StudentID== stuID && p.ExamID == examID).Select(p => p.Score).Single();
                    result.CalendarID = db.ExamInfo.Where(p => p.ExamID == examID).Single().CalendarID;
                    result.CalendarName = db.ExamInfo.Where(p => p.ExamID == examID).Single().SchoolCalender.DisplayName;
                    result.ClassRank = Method.CalculateRankCount(result.Score, 
                        db.StudentInExam
                        .Where(p=>p.StudentInfo.ClassID==student.ClassID && p.ExamID==examID)
                        .Select(p=>p.Score).ToList());
                    result.GradeRank = Method.CalculateRankCount(result.Score,
                        db.StudentInExam
                        .Where(p => p.ExamID == examID)
                        .Select(p => p.Score).ToList());
                    results.Add(result);
                }
                return results;
            }
        }
    }
}
